using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Xml;

namespace Spike.TestHarness.Controls
{
    public partial class XmlEditControl : UserControl
    {
        enum ViewMode { Text, Tree };

        public XmlEditControl()
        {
            InitializeComponent();
        }

        private void SetViewMode(ViewMode viewMode)
        {
            if (viewMode == ViewMode.Text)
            {
                TreeViewToText();

                txtInput.Visible = true;
                tv.Visible = false;
            }
            else
            {
                if (TextToTreeView(txtInput.Text))
                {
                    tv.Visible = true;
                    txtInput.Visible = false;
                }
                else
                {
                    MessageBox.Show("Unable to switch to tree view.  Please verify the text is valid xml.", "Error switching views", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    SetViewMode(ViewMode.Text);
                }
            }

        }

        public string Content
        {
            get 
            {
                if (rdoText.Checked)
                    return txtInput.Text;
                else
                    return TreeViewToText();
            }
            set 
            {
                txtInput.Text = value;
                rdoTree.Checked = value != string.Empty;
                //SetViewMode(ViewMode.Tree);                           
            }
        }

        private void radioButton1_CheckedChanged(object sender, EventArgs e)
        {
            if(rdoText.Checked)
                SetViewMode(ViewMode.Text);
            else
                SetViewMode(ViewMode.Tree);
        }
       
        

        private string TreeViewToText()
        {
            XmlDocument doc = new XmlDocument();
            doc.AppendChild(TreeNodeToXmlNode(doc, tv.Nodes[0]));

            return doc.OuterXml;
        }

        private XmlNode TreeNodeToXmlNode(XmlDocument doc, TreeNode treeNode)
        {
            XmlNode node = null;

            XmlNode from = treeNode.Tag as XmlNode;

            node = doc.CreateElement(from.Name, from.NamespaceURI);

            foreach (TreeNode tn in treeNode.Nodes)
            {
                if (tn.Nodes.Count == 0)
                {
                    node.AppendChild(doc.CreateTextNode(tn.Text));                    
                }
                else
                {                    
                    node.AppendChild(TreeNodeToXmlNode(doc, tn));
                }
            }

            return node;               
        }

        public bool TextToTreeView(string content)
        {
            try
            {
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(content);

                tv.Nodes.Clear();

                tv.Nodes.Add(new TreeNode(BuildNodeName(doc.DocumentElement)));
                TreeNode tNode = new TreeNode();
                tNode = tv.Nodes[0];
                tNode.Tag = doc.DocumentElement;

                AddNode(doc.DocumentElement, tNode);
                tv.ExpandAll();

                return true;
            }
            catch (Exception)
            {

                return false;
            }            
        }

        private void AddNode(XmlNode inXmlNode, TreeNode inTreeNode)
        {
            XmlNode xNode;
            TreeNode tNode;
            XmlNodeList nodeList;
            int i;

            // Loop through the XML nodes until the leaf is reached.
            // Add the nodes to the TreeView during the looping process.
            if (inXmlNode.HasChildNodes)
            {
                nodeList = inXmlNode.ChildNodes;
                for (i = 0; i <= nodeList.Count - 1; i++)
                {
                    xNode = inXmlNode.ChildNodes[i];
                    TreeNode node = new TreeNode(BuildNodeName(xNode));
                    node.Tag = xNode;
                    inTreeNode.Nodes.Add(node);
                    tNode = inTreeNode.Nodes[i];
                    AddNode(xNode, tNode);
                }
            }
            else
            {
                // Here you need to pull the data from the XmlNode based on the
                // type of node, whether attribute values are required, and so forth.
                inTreeNode.Text = (inXmlNode.OuterXml).Trim();
                inTreeNode.Tag = inXmlNode;

            }
        }

        private static string BuildNodeName(XmlNode xNode)
        {
            if (xNode.NamespaceURI == string.Empty)
                return xNode.Name;
            else
                return string.Format("{0} xmlns=\"{1}\"", xNode.Name, xNode.NamespaceURI);
        }

        private void tv_AfterLabelEdit(object sender, NodeLabelEditEventArgs e)
        {
            XmlText node = e.Node.Tag as XmlText;

            string s = e.Label;

            if (node == null)
            {
                MessageBox.Show("Only leaf nodes can be updated in the Tree View.", "Failed to update Xml Document", MessageBoxButtons.OK, MessageBoxIcon.Error);
                e.CancelEdit = true;
            }
            else
            {
                node.Value = e.Label;
            }                       
        }

    }
}
